import { isUndefined, isNull, PagedList, PageParams, toString } from "mmb";
import * as brand_distribute_requestpb from "../grpc-client/service/brand_distribute_request_pb";
import { jsTimestampToPb, pbTimestampToJs } from "./helper";
import GrpcErrCode from "../grpc-client/grpcErrCode";
import AuditResult from "../bg-enums/auditResult";
import {
  getBgsBrandDistributeRequestOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";

import {
  BrandDistributeRequest,
  BrandDistributeRequestWithUserInfo,
  ApplyBrandDistributeRequestParams,
  AuditBrandDistributeRequestParams,
} from "./declareTypes";
/****************************************************************************************/
/*                                   brand_distribute_request entity                       */
/****************************************************************************************/

const brandDistributeRequestPbToObject = (
  pb: brand_distribute_requestpb.BrandDistributeRequestEntity
): BrandDistributeRequest => {
  return {
    brandDistributeRequestId: `${pb.getId()}`,
    brandId: `${pb.getBrandId()}`,
    userId: `${pb.getUserId()}`,
    requested: pbTimestampToJs(pb.getRequested())!,
    audited: pbTimestampToJs(pb.getAudited()),
    applyFields: pb.getApplyFields(),
    auditResult: pb.getAuditResult() as AuditResult,
  };
};

/****************************************************************************************/
/*                                   brand_distribute_request cmd                          */
/****************************************************************************************/

export const applyBrandDistributeRequest = async ({
  brandId,
  userId,
  applyFields,
}: ApplyBrandDistributeRequestParams): Promise<BrandDistributeRequest> => {
  const cl = getBgsBrandDistributeRequestOpSafely();
  const req =
    new brand_distribute_requestpb.ApplyBrandDistributeRequestRequest();

  req.setBrandId(Number(brandId));
  req.setUserId(Number(userId));
  req.setApplyFields(applyFields);

  return new Promise((resolve, reject) => {
    cl.applyBrandDistributeRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(
          brandDistributeRequestPbToObject(res.getBrandDistributeRequest()!)
        );
      }
    );
  });
};

export const auditBrandDistributeRequest = async ({
  brandDistributeRequestId,
  audited,
  auditResult,
}: AuditBrandDistributeRequestParams): Promise<BrandDistributeRequest> => {
  const cl = getBgsBrandDistributeRequestOpSafely();
  const req =
    new brand_distribute_requestpb.AuditBrandDistributeRequestRequest();

  req.setId(Number(brandDistributeRequestId));
  req.setAudited(jsTimestampToPb(audited));
  req.setAuditResult(auditResult);

  return new Promise((resolve, reject) => {
    cl.auditBrandDistributeRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(
          brandDistributeRequestPbToObject(res.getBrandDistributeRequest()!)
        );
      }
    );
  });
};

/****************************************************************************************/
/*                                   brand_distribute_request query                        */
/****************************************************************************************/

export const getBrandDistributeRequest = async (
  brandDistributeRequestId: string
): Promise<BrandDistributeRequest> => {
  const cl = getBgsBrandDistributeRequestOpSafely();
  const req = new brand_distribute_requestpb.GetBrandDistributeRequestRequest();

  req.setId(Number(brandDistributeRequestId));

  return new Promise((resolve, reject) => {
    cl.getBrandDistributeRequest(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(
          brandDistributeRequestPbToObject(res.getBrandDistributeRequest()!)
        );
      }
    );
  });
};

export interface getBrandDistributeRequestByBrandIDAndUserIDRet {
  brandDistributeRequest?: BrandDistributeRequest;
  distribtorId?: string;
}

export const getBrandDistributeRequestByBrandIDAndUserID = async (
  brandId: string,
  userId: string
): Promise<getBrandDistributeRequestByBrandIDAndUserIDRet> => {
  const cl = getBgsBrandDistributeRequestOpSafely();
  const req =
    new brand_distribute_requestpb.GetBrandDistributeRequestByBrandIDAndUserIDRequest();

  req.setBrandId(Number(brandId));
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.getBrandDistributeRequestByBrandIDAndUserID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          if (opRet.getCode() === GrpcErrCode.NOT_FOUND) {
            resolve({});
            return;
          } else {
            reject(wrapperGrpcError(opRet.getMsg()));
            return;
          }
        }
        resolve({
          brandDistributeRequest: brandDistributeRequestPbToObject(
            res.getBrandDistributeRequest()!
          ),
          distribtorId:
            res.getDistributorId() === 0
              ? undefined
              : toString(res.getDistributorId()),
        });
      }
    );
  });
};

/****************************************************************************************/
/*                                   brand_distribute_requestJoins entity                  */
/****************************************************************************************/

const brandDistributeRequestWithUserInfoPbToObject = (
  pb: brand_distribute_requestpb.BrandDistributeRequestWithUserInfoEntity
): BrandDistributeRequestWithUserInfo => {
  return {
    brandDistributeRequestId: `${pb.getId()}`,
    brandId: `${pb.getBrandId()}`,
    userId: `${pb.getUserId()}`,
    requested: pbTimestampToJs(pb.getRequested())!,
    audited: pbTimestampToJs(pb.getAudited()),
    applyFields: pb.getApplyFields(),
    auditResult: pb.getAuditResult() as AuditResult,
    userPic: pb.getUserPic(),
  };
};

/****************************************************************************************/
/*                                   brand_distribute_requestJoins query                   */
/****************************************************************************************/

export const listBrandDistributeRequestWithUserInfosByBrandID = async (
  brandId: string,
  isWaitAudit: boolean,
  pager: PageParams
): Promise<PagedList<BrandDistributeRequest>> => {
  const cl = getBgsBrandDistributeRequestOpSafely();
  const req =
    new brand_distribute_requestpb.ListBrandDistributeRequestWithUserInfosByBrandIDRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setBrandId(Number(brandId));
  let auditResults = isWaitAudit
    ? [AuditResult.PENDING]
    : [AuditResult.APPROVED, AuditResult.REJECTED];
  req.setAuditResultsList(auditResults);

  return new Promise((resolve, reject) => {
    cl.listBrandDistributeRequestWithUserInfosByBrandID(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<BrandDistributeRequest> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getBrandDistributeRequestWithUserInfosList()
          .map(brandDistributeRequestWithUserInfoPbToObject);
        resolve(ret);
      }
    );
  });
};
